package com.ruiyian.netty.nettyserver;

import com.ruiyian.common.constant.*;
import com.ruiyian.common.core.domain.AjaxResult;
import com.ruiyian.common.core.domain.entity.Point;
import com.ruiyian.common.core.redis.RedisCache;
import com.ruiyian.common.enums.ReturnType;
import com.ruiyian.common.utils.DateUtils;
import com.ruiyian.common.utils.JSON;
import com.ruiyian.common.utils.jfinsUtil.FinsMessage;
import com.ruiyian.common.utils.jfinsUtil.FinsMessageUtils;
import com.ruiyian.common.utils.spring.SpringUtils;
import com.ruiyian.netty.nettyclient.NettyStarter;
import com.ruiyian.project.equipment.service.PointService;
import com.ruiyian.project.log.domain.PlanLogMain;
import com.ruiyian.project.log.service.PlanLogMainService;
import com.ruiyian.system.domain.ServerEq;
import com.ruiyian.system.domain.ServerPointFormal;
import com.ruiyian.system.domain.vo.ServerEqFormal;
import com.ruiyian.system.service.ServerPointService;
import com.ruiyian.system.service.ServerService;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.buffer.UnpooledHeapByteBuf;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.CharsetUtil;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RLock;

import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.ruiyian.netty.DataUtils.DataUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.ReactiveSetCommands;
import org.springframework.jdbc.core.JdbcTemplate;

/**
 * @author chong
 * @email 673426164@qq.com
 * @create 2020/12/21
 * Desc: 建立连接
 */
@Slf4j
public class MyWebSocketHandler extends ChannelInboundHandlerAdapter {
    // 预案信息
//    private static PlanService planService;
    private static RedisCache redisCache;
    private static PointService pointService;
    private static Redisson redisson;
    private String type;
    private static ServerService serverService;
    private static PlanLogMainService planLogMainService;
    private List<Point> data;
    private static JdbcTemplate jdbcTemplate;
    private static ServerPointService serverPointService;
    private String secure_board_msg2 = "0230303130706C61792E6C73742B000000005B506C61796C6973745D0D0A4974656D5F4E6F3D310D0A4974656D303D3530302C312C352C5C6673333233325C433030303030305C5330305C63323535323535303030303030BDF7C9F7BCDDCABB205C6673333233325C433030303033325C5330305C63323535323535303030303030BCF5CBD9C2FDD0D0701E03";
    private String secure_board_msg1 = "0230303130706C61792E6C73742B000000005B506C61796C6973745D0D0A4974656D5F4E6F3D310D0A4974656D303D3530302C312C352C5C6673333233325C433030303030305C5330305C63323535323535303030303030CEC4C3F7BCDDCABB205C6673333233325C433030303033325C5330305C63323535323535303030303030D7A2D2E2B0B2C8AB9FAB03";
    private String accident_board_msg1 = "0230303130706C61792E6C73742B000000005B506C61796C6973745D0D0A4974656D5F4E6F3D310D0A4974656D303D3530302C312C352C5C6673333233325C433030303030305C5330305C63323535323535303030303030CBEDB5C0CAC2B9CA205C6673333233325C433030303033325C5330305C63323535323535303030303030BDFBD6B9CDA8D0D0409803";

    static {
        planLogMainService = SpringUtils.getBean(PlanLogMainService.class);
//        planService = SpringUtils.getBean(PlanService.class);
        redisCache = SpringUtils.getBean(RedisCache.class);
        pointService = SpringUtils.getBean(PointService.class);
        redisson = SpringUtils.getBean(Redisson.class);
        serverService = SpringUtils.getBean(ServerService.class);
        serverPointService = SpringUtils.getBean(ServerPointService.class);
        jdbcTemplate = SpringUtils.getBean(JdbcTemplate.class);
    }

    public MyWebSocketHandler(String type) {
        this.type = type;


    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        redisCache.setCacheObject("CurrentActiveModule", null);
        InetSocketAddress ipSocket = (InetSocketAddress) ctx.channel().remoteAddress();
        int port = ipSocket.getPort();
        String host = ipSocket.getHostString();
        log.info(type + "-->与websocket客户端" + host + ":" + port + "建立连接!");
        //添加到channelGroup通道组
        if (Constants.TCP.equals(type)) {
            MyChannelHandlerPool.tcpChannelGroup.add(ctx.channel());
        } else {
            MyChannelHandlerPool.channelGroup.add(ctx.channel());
        }
        super.channelActive(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        redisCache.setCacheObject("CurrentActiveModule", "0");
        log.info("与客户端断开连接，通道关闭！");
        //移除channelGroup 通道组
        if (Constants.TCP.equals(type)) {
            MyChannelHandlerPool.tcpChannelGroup.remove(ctx.channel());
        } else {
            MyChannelHandlerPool.channelGroup.remove(ctx.channel());
        }
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 存储网页发来的消息
        JSONObject json = null;
        // 返回消息
        JSONObject jsonReturn = new JSONObject();
        // 激活模块
        String currentactivemodule = "0";
        try {
            PlanLogMain planLogMain = new PlanLogMain(); // 联动预案日志
            InetSocketAddress ipSocket = (InetSocketAddress) ctx.channel().remoteAddress();
            int port = ipSocket.getPort();
            String host = ipSocket.getHostString();
            log.info(type + "-->接收到是host：" + host + "端口:" + port);
            String operateType = "";
            String lockKey = "client_port_model";
            // 如果是tcp的话
            if (Constants.TCP.equals(type)) {
                ByteBuf in = (ByteBuf) msg;
                int readableBytes = in.readableBytes();
                byte[] bytes = new byte[readableBytes];
                in.readBytes(bytes);
                String str = new String(bytes);
                log.info("服务端接收到消息:" + str);
                json = JSONObject.fromObject(str);
                planLogMain.setConditions(str);
            }
            // 如果是websocket的话
            else {
                TextWebSocketFrame frame = (TextWebSocketFrame) msg;
                log.info("服务端接收到消息：" + frame.text());
                json = JSONObject.fromObject(frame.text());
                planLogMain.setConditions(frame.text());
            }
            // 如果网页端发来关闭连接，那就关闭网页端的连接
            if (json.getString("type").equals("close")) {
                // 客户端关闭连接,websocket移除连接
                MyChannelHandlerPool.channelGroup.remove(ctx.channel());
                // 恢复当前激活模块
                redisCache.setCacheObject("CurrentActiveModule", "0");
                return;
            }
            // 存储当前激活模块
            if(json.containsKey("moniStructure") && json.containsKey("tunnelId") && json.containsKey("moduleId")){
                currentactivemodule = json.getString("moniStructure")+"/"+json.getString("tunnelId")+"/"+json.getString("moduleId")
                    +"/"+json.getString("servernameEn");
                redisCache.setCacheObject("CurrentActiveModule", currentactivemodule);
            }
            // 如果是ip广播和情报板，则不需要判断是哪一个模块,直接处理
            if(json.getString("servernameEn").startsWith(ServerNameEn.IP_SPEAKER)){
                // 筛选出服务列表
                List<ServerEqFormal> ipspearkerserverList = serverService.selectServerformalByInfo(0, 0,
                    json.containsKey("servernameEn")?json.getString("servernameEn"):null);
                Map<String, ChannelFuture> connectMap = NettyStarter.getConnectMap(); // 通过netty获取所有连接状态
                // 对服务列表进行筛选，只保留处于连接的设备
                for(int i = 0; i < ipspearkerserverList.size(); i++) {
                    if(!connectMap.containsKey(ipspearkerserverList.get(i).getHost() + ":" +ipspearkerserverList.get(i).getPort())){
                        ipspearkerserverList.remove(i);
                        i--;
                    }
                }
                if(ipspearkerserverList.size()!=1){
                    Map<String,String> deviceInfo = new HashMap<String,String>();
                    jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                    if(ipspearkerserverList.size()==0){
                        jsonReturn.put("code", FinsStatus.NO_DEVICE);
                        jsonReturn.put("msg", "无喇叭设备");
                        jsonReturn.put("deviceInfo", deviceInfo);
                    }
                    if(ipspearkerserverList.size()>1){
                        jsonReturn.put("code", FinsStatus.DEVICE_OVERQUANTUTY);
                        jsonReturn.put("msg", "喇叭设备不唯一");
                        jsonReturn.put("deviceInfo", deviceInfo);
                    }
                    ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                    return;
                }
                else {
                    // 控制广播发声
                    if((json.getString("type").equals("write"))){
                        // 获取完整地址
                        String serverpath = ipspearkerserverList.get(0).getHost()+":"+ipspearkerserverList.get(0).getPort();
                        ChannelFuture channelFuture = connectMap.get(serverpath);
                        // 下发广播控制数据
                        JSONObject speakerMsgJson = new JSONObject();
                        speakerMsgJson = json.getJSONObject("value");
                        String content = speakerMsgJson.getString("content");
                        int clienid = speakerMsgJson.getInt("clienid");
                        // 根据clienid区分
                        if(clienid==9999){
                            byte[] speakerMsgBytes = DataUtils.getSpeakerArray(content);
                            channelFuture.channel().writeAndFlush(Unpooled.wrappedBuffer(speakerMsgBytes));
                        }
                        else {
                            byte[] speakerMsgBytes = DataUtils.getSpeakerArray(clienid, content);
                            channelFuture.channel().writeAndFlush(Unpooled.wrappedBuffer(speakerMsgBytes));
                        }
                        // 上发发送成功的消息
                        jsonReturn.clear();
                        Map<String,String> deviceInfo = new HashMap<String,String>();
                        deviceInfo.put("content", content);
                        deviceInfo.put("clienid", Integer.toString(clienid));
                        jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                        jsonReturn.put("servernameEn", json.containsKey("servernameEn") ? json.getString("servernameEn") : "0");
                        jsonReturn.put("code", FinsStatus.SEND_SUCCESS);
                        jsonReturn.put("msg", "广播设置成功");
                        jsonReturn.put("deviceInfo", deviceInfo);
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                        return;
                    }
                }
            }
            // 情报板，不需要判断哪一个模块，直接处理
            if(json.getString("servernameEn").startsWith(ServerNameEn.IP_BOARD)){
                // 筛选出服务列表
                List<ServerEqFormal> ipboardserverList = serverService.selectServerformalByInfo(json.getInt("tunnelId"), json.getInt("moduleId"),
                    json.containsKey("servernameEn")?json.getString("servernameEn"):null);
                Map<String, ChannelFuture> connectMap = NettyStarter.getConnectMap(); // 通过netty获取所有连接状态
                // 对服务列表进行筛选，只保留处于连接的设备
                for(int i = 0; i < ipboardserverList.size(); i++) {
                    if(!connectMap.containsKey(ipboardserverList.get(i).getHost() + ":" +ipboardserverList.get(i).getPort())){
                        ipboardserverList.remove(i);
                        i--;
                    }
                }
                if(ipboardserverList.size()!=1){
                    Map<String,String> deviceInfo = new HashMap<String,String>();
                    jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                    if(ipboardserverList.size()==0){
                        jsonReturn.put("code", FinsStatus.NO_DEVICE);
                        jsonReturn.put("msg", "无情报板设备");
                        jsonReturn.put("deviceInfo", deviceInfo);
                    }
                    if(ipboardserverList.size()>1){
                        jsonReturn.put("code", FinsStatus.DEVICE_OVERQUANTUTY);
                        jsonReturn.put("msg", "情报板设备不唯一");
                        jsonReturn.put("deviceInfo", deviceInfo);
                    }
                    ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                    return;
                }
                else {
                    if((json.getString("type").equals("write"))){
                        // 获取完整地址
                        String serverpath = ipboardserverList.get(0).getHost()+":"+ipboardserverList.get(0).getPort();
                        ChannelFuture channelFuture = connectMap.get(serverpath);
                        // 下发情报板控制数据
                        JSONObject boardMsgJson = new JSONObject();
                        boardMsgJson = json.getJSONObject("value");
                        String content = boardMsgJson.getString("content");
                        String color = boardMsgJson.getString("color");
                        byte[] boardMsgBytes = DataUtils.getMsgBoardArray(content);
                        channelFuture.channel().writeAndFlush(Unpooled.wrappedBuffer(boardMsgBytes));
                        // 上发发送成功的消息
                        jsonReturn.clear();
                        Map<String,String> deviceInfo = new HashMap<String,String>();
                        deviceInfo.put("content", content);
                        deviceInfo.put("color", color);
                        jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                        jsonReturn.put("servernameEn", json.containsKey("servernameEn") ? json.getString("servernameEn") : "0");
                        jsonReturn.put("code", FinsStatus.SEND_SUCCESS);
                        jsonReturn.put("msg", "情报板设置成功");
                        jsonReturn.put("deviceInfo", deviceInfo);
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                        // 把发送的数据存到数据库
                        String sqlSelect = String.format("select * FROM board_operation_information WHERE content='%s' AND del_flag='0'", content);
                        if(jdbcTemplate.queryForList(sqlSelect).size()==0){
                            String sqlInsert = String.format("insert into board_operation_information(server_id,content) values('%s','%s')", ipboardserverList.get(0).getId(),content);
                            jdbcTemplate.update(sqlInsert);
                        }
                        return;
                    }
                    else if((json.getString("type").equals("query"))){
                        // 上发发送成功的消息
                        jsonReturn.clear();
                        Map<String,String> deviceInfo = new HashMap<String,String>();
                        jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                        jsonReturn.put("servernameEn", json.containsKey("servernameEn") ? json.getString("servernameEn") : "0");
                        jsonReturn.put("code", FinsStatus.SEND_SUCCESS);
                        jsonReturn.put("msg", "情报板数据获取成功");
                        jsonReturn.put("deviceInfo", deviceInfo);
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                        return;
                    }
                }

            }
            // 雷达测速，不需要判断哪一个模块，直接处理
            if(json.getString("servernameEn").startsWith(ServerNameEn.RADAR_SPEED_MSU)){

                return;
            }
            // *******判断是获取哪一种结构物数据
            // 如果是操作/获取桥梁数据（udp设备）
            if(json.get("moniStructure").equals("bridge")){
                Map<String,String> deviceInfo = new HashMap<String,String>();
                jsonReturn.clear();
                jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                // 进来后直接取数据，复用memoryArea取数据
                String deviceId = (String) json.get("memoryArea");
                Map<String, String> bridgeDataMap = redisCache.getCacheObject("bridge/icedetect/"+deviceId);
                // 无数据或者是时间超长，则代表不在线
                if(bridgeDataMap==null || Math.abs(Long.parseLong(bridgeDataMap.get("timestamp"))-System.currentTimeMillis())/1000>30){
                    jsonReturn.put("code", FinsStatus.NO_DEVICE);
                    jsonReturn.put("msg", deviceId+"未在线");
                    deviceInfo.put(deviceId,"disconnected");
                }
                else {
                    // 连接测试
                    if(json.get("type").equals("connect")){
                        jsonReturn.put("code", FinsStatus.SUCCESS);
                        jsonReturn.put("msg", deviceId+"在线");
                        deviceInfo.put(deviceId,"connected");
                    }
                    // 取数据
                    else if(json.get("type").equals("query")){
                        jsonReturn.put("code", FinsStatus.SUCCESS);
                        jsonReturn.put("msg", deviceId+"在线");
                        jsonReturn.put("deviceInfo", bridgeDataMap);
                    }
                    else {
                        jsonReturn.put("code", FinsStatus.COMMAND_ERROR);
                        jsonReturn.put("msg", "指令错误");
                    }
                }
                // 将数据通过websocket发回给前端
                ctx.channel().writeAndFlush(new TextWebSocketFrame(JSON.stringify(jsonReturn)));
                return;
            }
            // 如果是操作/获取隧道数据（tcp设备，包括fins设备）
            else if(json.get("moniStructure").equals("tunnel")) {
                // 区分是哪个模块
                // 交通控制模块
                if(json.get("moduleId").equals(ModuleIdList.TRAFFIC_CONTROL)) {
                    // 创建发送给plc的fins消息
                    FinsMessage finsMessage = null;
                    // 筛选出服务列表
                    List<ServerEqFormal> trafficControlserverList = serverService.selectServerformalByInfo(json.getInt("tunnelId"), json.getInt("moduleId"),
                        json.containsKey("servernameEn") ? json.getString("servernameEn") : null);
                    Map<String, ChannelFuture> connectMap = NettyStarter.getConnectMap(); // 通过netty获取所有连接状态
                    // 对服务列表进行筛选，只保留处于连接的设备
                    for (int i = 0; i < trafficControlserverList.size(); i++) {
                        if (!connectMap.containsKey(trafficControlserverList.get(i).getHost() + ":" + trafficControlserverList.get(i).getPort())) {
                            trafficControlserverList.remove(i);
                            i--;
                        }
                    }
                    // 判断服务数量是否正常，唯一才是正常的
                    if (trafficControlserverList.size() != 1) {
                        Map<String, String> deviceInfo = new HashMap<String, String>();
                        deviceInfo.put("memoryArea", json.containsKey("memoryArea") ? json.getString("memoryArea") : null);
                        deviceInfo.put("registerAddress", json.containsKey("registerAddress") ? json.getString("registerAddress") : null);
                        deviceInfo.put("bits", json.containsKey("bits") ? json.getString("bits") : null);
                        deviceInfo.put("length", json.containsKey("length") ? json.getString("length") : null);
                        jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                        jsonReturn.put("tunnelId", json.containsKey("tunnelId") ? json.getString("tunnelId") : null);
                        jsonReturn.put("moduleId", json.containsKey("moduleId") ? json.getString("moduleId") : null);
                        if (trafficControlserverList.size() == 0) {
                            jsonReturn.put("code", FinsStatus.NO_DEVICE);
                            jsonReturn.put("msg", "无交通控制PLC设备连接");
                            jsonReturn.put("deviceInfo", deviceInfo);
                        }
                        if (trafficControlserverList.size() > 1) {
                            jsonReturn.put("code", FinsStatus.DEVICE_OVERQUANTUTY);
                            jsonReturn.put("msg", "交通控制PLC设备不唯一");
                            jsonReturn.put("deviceInfo", deviceInfo);
                        }
                        // 将报警信息发送给前端
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                        return;
                    }
                    // 获取完整地址
                    String serverpath = trafficControlserverList.get(0).getHost() + ":" + trafficControlserverList.get(0).getPort();
                    String dev_value = "0";
                    // 获取连接
                    ChannelFuture channelFuture = connectMap.get(serverpath);
                    // 读操作
                    if (json.get("type").equals("query")) {
                        jsonReturn.clear();
                        jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                        jsonReturn.put("tunnelId", json.containsKey("tunnelId") ? json.getString("tunnelId") : null);
                        jsonReturn.put("moduleId", json.containsKey("moduleId") ? json.getString("moduleId") : null);
                        Map<String, String> deviceInfo = new HashMap<String, String>();
                        // 多设备状态查询,复用memoryArea查询是否为设备查询
                        if (json.getInt("memoryArea") == 9999) {
                            String keysPattern = String.format("*%s/%s/%s*", json.getString("servernameEn"),json.getString("tunnelId"), json.getString("moduleId"));
                            // 获取该设备的所有点位的键
                            Collection<String> trafficKeys = redisCache.keys(keysPattern);
                            if(trafficKeys.size()>0){
                                jsonReturn.put("code", FinsStatus.SUCCESS);
                                jsonReturn.put("msg", "交通控制PLC数据获取成功");
                                for(String trafficKey:trafficKeys){
                                    String[] keySplit = trafficKey.split("/");
                                    String registerAddress = String.valueOf(Integer.parseInt(keySplit[4])-90);
                                    String bits = keySplit[6];
                                    dev_value = redisCache.getCacheObject(trafficKey);
                                    if (dev_value != null){
                                        deviceInfo.put(registerAddress+"/"+bits, dev_value);
                                    }
                                    else {
                                        deviceInfo.put(registerAddress+"/"+bits, "NoData");
                                    }
                                }
                            }
                            else {
                                jsonReturn.put("code", FinsStatus.NO_RETURN_DATA);
                                jsonReturn.put("msg", "交通控制PLC无点位数据");
                            }
                        }
                        // 单查询
                        else {
                            String CurrentRequestFinsDevId = json.getString("servernameEn")+"/" + json.getString("tunnelId") + "/" +
                                json.getString("moduleId") + "/" +
                                json.getString("memoryArea") + "/" +
                                json.getString("registerAddress") + "/" +
                                json.getString("length") + "/" +
                                json.getString("bits");
                            dev_value = redisCache.getCacheObject(CurrentRequestFinsDevId);
                            if (dev_value != null) {
                                jsonReturn.put("code", FinsStatus.SUCCESS);
                                jsonReturn.put("msg", "交通控制PLC数据获取成功");
                                deviceInfo.put(json.getString("registerAddress") + json.getString("bits"), dev_value);
                            } else {
                                jsonReturn.put("code", FinsStatus.NO_RETURN_DATA);
                                jsonReturn.put("msg", "交通控制PLC数据未获取成功");
                                deviceInfo.put(json.getString("registerAddress") + json.getString("bits"), "NoData");
                            }
                        }
                        // 将数据传到了网页
                        jsonReturn.put("deviceInfo", deviceInfo);
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                        return;
                    }
                    // 写操作
                    else if (json.get("type").equals("write")) {
                        finsMessage = FinsMessageUtils.createWriteMessage(json.getInt("memoryArea"), json.getInt("registerAddress"),
                            json.getInt("bits"), json.getInt("value"), serverpath);
                        // 二次判断，看fins数据是否生成
                        if (finsMessage != null) {
                            // 把fins消息发送给plc
                            if (channelFuture != null && channelFuture.isSuccess()) {
                                // 将finse数据发给plc
                                channelFuture.channel().writeAndFlush(finsMessage.toString()).sync();
                                // 生成发送给网页的数据
                                Map<String, String> deviceInfo = new HashMap<String, String>();
                                deviceInfo.put("memoryArea", json.containsKey("memoryArea") ? json.getString("memoryArea") : null);
                                deviceInfo.put("registerAddress", json.containsKey("registerAddress") ? json.getString("registerAddress") : null);
                                deviceInfo.put("bits", json.containsKey("bits") ? json.getString("bits") : null);
                                deviceInfo.put("length", json.containsKey("length") ? json.getString("length") : null);
                                deviceInfo.put("value", json.containsKey("value") ? json.getString("value") : null);
                                jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                                jsonReturn.put("tunnelId", json.containsKey("tunnelId") ? json.getString("tunnelId") : null);
                                jsonReturn.put("moduleId", json.containsKey("moduleId") ? json.getString("moduleId") : null);
                                jsonReturn.put("code", FinsStatus.SEND_SUCCESS);
                                jsonReturn.put("msg", "交通控制PLC设备设置成功");
                                jsonReturn.put("deviceInfo", deviceInfo);
                                // 将操作成功的数据上发给网页端
                                ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                            }
                        }
                    }
                    // 指令错误
                    else {
                        jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                        jsonReturn.put("code", FinsStatus.COMMAND_ERROR);
                        jsonReturn.put("msg", "操作指令错误");
                        // 发送操作指令的信息给网页
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                        log.info("操作指令错误");
                    }
                    return;
                }
                // 照明控制模块
                if(json.get("moduleId").equals(ModuleIdList.LIGHT_CONTROL)){
                    // 创建发送给plc的fins消息
                    FinsMessage finsMessage = null;
                    // 筛选出服务列表
                    List<ServerEqFormal> lightserverList = serverService.selectServerformalByInfo(json.getInt("tunnelId"), json.getInt("moduleId"),
                        json.containsKey("servernameEn")?json.getString("servernameEn"):null);
//                    List<ServerEq> visualinductionserverList = serverService.selectServerByTunnelId(json.getLong("tunnelId"), json.getLong("moduleId"));
                    Map<String, ChannelFuture> connectMap = NettyStarter.getConnectMap(); // 通过netty获取所有连接状态
                    // 对服务列表进行筛选，只保留处于连接的设备
                    for(int i = 0; i < lightserverList.size(); i++) {
                        if(!connectMap.containsKey(lightserverList.get(i).getHost() + ":" +lightserverList.get(i).getPort())){
                            lightserverList.remove(i);
                            i--;
                        }
                    }
                    // 判断服务数量是否正常，唯一才是正常的
                    if(lightserverList.size()!=1){
                        Map<String,String> deviceInfo = new HashMap<String,String>();
                        deviceInfo.put("memoryArea", json.containsKey("memoryArea") ? json.getString("memoryArea") : null);
                        deviceInfo.put("registerAddress", json.containsKey("registerAddress") ? json.getString("registerAddress") : null);
                        deviceInfo.put("bits", json.containsKey("bits") ? json.getString("bits") : null);
                        deviceInfo.put("length", json.containsKey("length") ? json.getString("length") : null);
                        jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                        jsonReturn.put("tunnelId", json.containsKey("tunnelId") ? json.getString("tunnelId") : null);
                        jsonReturn.put("moduleId", json.containsKey("moduleId") ? json.getString("moduleId") : null);
                        if(lightserverList.size()==0){
                            jsonReturn.put("code", FinsStatus.NO_DEVICE);
                            jsonReturn.put("msg", "无照明控制PLC设备连接");
                            jsonReturn.put("deviceInfo", deviceInfo);
                        }
                        if(lightserverList.size()>1){
                            jsonReturn.put("code", FinsStatus.DEVICE_OVERQUANTUTY);
                            jsonReturn.put("msg", "照明控制PLC设备不唯一");
                            jsonReturn.put("deviceInfo", deviceInfo);
                        }
                        // 将报警信息发送给前端
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                        return;
                    }
                    // 获取完整地址
                    String serverpath = lightserverList.get(0).getHost()+":"+lightserverList.get(0).getPort();
                    String dev_value = "0";
                    // 获取连接
                    ChannelFuture channelFuture = connectMap.get(serverpath);
                    // 读操作
                    if(json.get("type").equals("query")){
                        jsonReturn.clear();
                        jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                        jsonReturn.put("tunnelId", json.containsKey("tunnelId") ? json.getString("tunnelId") : null);
                        jsonReturn.put("moduleId", json.containsKey("moduleId") ? json.getString("moduleId") : null);
                        Map<String,String> deviceInfo = new HashMap<String,String>();
                        // 多设备状态查询,复用memoryArea查询是否为设备查询
                        if(json.getInt("memoryArea")==9999){
                            List<ServerPointFormal> lightControlPointList=new ArrayList<>();
                            if(currentactivemodule.equals(ActiveModule.LIGHT_CONTROL_24)){
                                lightControlPointList= serverPointService.getserverpoint(18);
                            }
                            else if(currentactivemodule.equals(ActiveModule.LIGHT_CONTROL_25)){
                                lightControlPointList= serverPointService.getserverpoint(19);
                            }
                            if(lightControlPointList.size()>0){
                                for(ServerPointFormal serverPointFormal:lightControlPointList){
                                    int tunnelId = serverPointFormal.getTunnel_id();
                                    int moduleId = serverPointFormal.getModule_id();
                                    int memoryArea = serverPointFormal.getMemory_area();
                                    int registerAddress = (int) serverPointFormal.getRegister_address();
                                    int length = serverPointFormal.getLength();
                                    int bits = serverPointFormal.getBits();
                                    dev_value = redisCache.getCacheObject(json.getString("servernameEn")+"/"+tunnelId+"/"+moduleId+"/"+memoryArea+"/"+registerAddress+"/"+length+"/"+bits);
                                    // 复用registerAddress信息存数据
                                    jsonReturn.put("code", FinsStatus.SUCCESS);
                                    jsonReturn.put("msg", "照明控制PLC数据获取成功");
                                    if(dev_value!=null){
                                        deviceInfo.put(registerAddress+"/"+bits, dev_value);
                                    }
                                    else {
                                        deviceInfo.put(registerAddress+"/"+bits, "NoData");
                                    }
                                }
                            }
                            else {
                                jsonReturn.put("code", FinsStatus.NO_RETURN_DATA);
                                jsonReturn.put("msg", "照明控制PLC无点位数据");
                            }
                        }
                        // 单查询
                        else {
                            String CurrentRequestFinsDevId = json.getString("servernameEn")+"/"+ json.getString("tunnelId")+"/"+
                                json.getString("moduleId")+"/"+
                                json.getString("memoryArea")+"/"+
                                json.getString("registerAddress")+"/"+
                                json.getString("length")+"/"+
                                json.getString("bits");
                            dev_value = redisCache.getCacheObject(CurrentRequestFinsDevId);
                            if(dev_value!=null){
                                jsonReturn.put("code", FinsStatus.SUCCESS);
                                jsonReturn.put("msg", "照明控制PLC数据获取成功");
                                deviceInfo.put(json.getString("registerAddress")+json.getString("bits"), dev_value);
                            }
                            else {
                                jsonReturn.put("code", FinsStatus.NO_RETURN_DATA);
                                jsonReturn.put("msg", "照明控制PLC数据未获取成功");
                                deviceInfo.put(json.getString("registerAddress")+json.getString("bits"), "NoData");
                            }
                        }
                        // 将数据传到了网页
                        jsonReturn.put("deviceInfo", deviceInfo);
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                    }
                    // 写操作
                    else if(json.get("type").equals("write")){
                        finsMessage = FinsMessageUtils.createWriteMessage(json.getInt("memoryArea"), json.getInt("registerAddress"),
                            json.getInt("bits"), json.getInt("value"), serverpath);
                        // 二次判断，看fins数据是否生成
                        if (finsMessage != null){
                            // 把fins消息发送给plc
                            if (channelFuture != null && channelFuture.isSuccess()) {
                                // 将finse数据发给plc
                                channelFuture.channel().writeAndFlush(finsMessage.toString()).sync();
                                // 生成发送给网页的数据
                                Map<String,String> deviceInfo = new HashMap<String,String>();
                                deviceInfo.put("memoryArea", json.containsKey("memoryArea") ? json.getString("memoryArea") : null);
                                deviceInfo.put("registerAddress", json.containsKey("registerAddress") ? json.getString("registerAddress") : null);
                                deviceInfo.put("bits", json.containsKey("bits") ? json.getString("bits") : null);
                                deviceInfo.put("length", json.containsKey("length") ? json.getString("length") : null);
                                deviceInfo.put("value", json.containsKey("value") ? json.getString("value") : null);
                                jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                                jsonReturn.put("tunnelId", json.containsKey("tunnelId") ? json.getString("tunnelId") : null);
                                jsonReturn.put("moduleId", json.containsKey("moduleId") ? json.getString("moduleId") : null);
                                jsonReturn.put("code", FinsStatus.SEND_SUCCESS);
                                jsonReturn.put("msg", "照明控制PLC设备设置成功");
                                jsonReturn.put("deviceInfo", deviceInfo);
                                // 将操作成功的数据上发给网页端
                                ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                            }
                        }
                    }
                    // 指令错误
                    else {
                        jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                        jsonReturn.put("code", FinsStatus.COMMAND_ERROR);
                        jsonReturn.put("msg", "操作指令错误");
                        // 发送操作指令的信息给网页
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                        log.info("操作指令错误");
                    }
                    return;
                }
                // 通风控制模块
                if(json.get("moduleId").equals(ModuleIdList.FAN_CONTROL)){
                    // 创建发送给plc的fins消息
                    FinsMessage finsMessage = null;
                    // 筛选出服务列表
                    List<ServerEqFormal> fanControlserverList = serverService.selectServerformalByInfo(json.getInt("tunnelId"), json.getInt("moduleId"),
                        json.containsKey("server_name_En") ? json.getString("server_name_En") : null);
                    Map<String, ChannelFuture> connectMap = NettyStarter.getConnectMap(); // 通过netty获取所有连接状态
                    // 对服务列表进行筛选，只保留处于连接的设备
                    for (int i = 0; i < fanControlserverList.size(); i++) {
                        if (!connectMap.containsKey(fanControlserverList.get(i).getHost() + ":" + fanControlserverList.get(i).getPort())) {
                            fanControlserverList.remove(i);
                            i--;
                        }
                    }
                    // 判断服务数量是否正常，唯一才是正常的
                    if (fanControlserverList.size() != 1) {
                        Map<String, String> deviceInfo = new HashMap<String, String>();
                        deviceInfo.put("memoryArea", json.containsKey("memoryArea") ? json.getString("memoryArea") : null);
                        deviceInfo.put("registerAddress", json.containsKey("registerAddress") ? json.getString("registerAddress") : null);
                        deviceInfo.put("bits", json.containsKey("bits") ? json.getString("bits") : null);
                        deviceInfo.put("length", json.containsKey("length") ? json.getString("length") : null);
                        jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                        jsonReturn.put("tunnelId", json.containsKey("tunnelId") ? json.getString("tunnelId") : null);
                        jsonReturn.put("moduleId", json.containsKey("moduleId") ? json.getString("moduleId") : null);
                        if (fanControlserverList.size() == 0) {
                            jsonReturn.put("code", FinsStatus.NO_DEVICE);
                            jsonReturn.put("msg", "无通风控制PLC设备连接");
                            jsonReturn.put("deviceInfo", deviceInfo);
                        }
                        if (fanControlserverList.size() > 1) {
                            jsonReturn.put("code", FinsStatus.DEVICE_OVERQUANTUTY);
                            jsonReturn.put("msg", "通风控制PLC设备不唯一");
                            jsonReturn.put("deviceInfo", deviceInfo);
                        }
                        // 将报警信息发送给前端
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                        return;
                    }
                    // 获取完整地址
                    String serverpath = fanControlserverList.get(0).getHost() + ":" + fanControlserverList.get(0).getPort();
                    String dev_value = "0";
                    // 获取连接
                    ChannelFuture channelFuture = connectMap.get(serverpath);
                    // 读操作
                    if (json.get("type").equals("query")) {
                        jsonReturn.clear();
                        jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                        jsonReturn.put("tunnelId", json.containsKey("tunnelId") ? json.getString("tunnelId") : null);
                        jsonReturn.put("moduleId", json.containsKey("moduleId") ? json.getString("moduleId") : null);
                        Map<String, String> deviceInfo = new HashMap<String, String>();
                        // 多设备状态查询,复用memoryArea查询是否为设备查询
                        if (json.getInt("memoryArea") == 9999) {
                            String keysPattern = String.format("*%s/%s/%s*", json.getString("servernameEn"),json.getString("tunnelId"), json.getString("moduleId"));
                            // 获取该设备的所有点位的键
                            Collection<String> trafficKeys = redisCache.keys(keysPattern);
                            if(trafficKeys.size()>0){
                                jsonReturn.put("code", FinsStatus.SUCCESS);
                                jsonReturn.put("msg", "通风控制PLC数据获取成功");
                                for(String trafficKey:trafficKeys){
                                    String[] keySplit = trafficKey.split("/");
                                    String registerAddress = keySplit[4];
                                    String bits = keySplit[6];
                                    dev_value = redisCache.getCacheObject(trafficKey);
                                    if (dev_value != null){
                                        deviceInfo.put(registerAddress+"/"+bits, dev_value);
                                    }
                                    else {
                                        deviceInfo.put(registerAddress+"/"+bits, "NoData");
                                    }
                                }
                            }
                            else {
                                jsonReturn.put("code", FinsStatus.NO_RETURN_DATA);
                                jsonReturn.put("msg", "通风控制PLC无点位数据");
                            }
                        }
                        // 单查询
                        else {
                            String CurrentRequestFinsDevId = json.getString("servernameEn")+"/" + json.getString("tunnelId") + "/" +
                                json.getString("moduleId") + "/" +
                                json.getString("memoryArea") + "/" +
                                json.getString("registerAddress") + "/" +
                                json.getString("length") + "/" +
                                json.getString("bits");
                            dev_value = redisCache.getCacheObject(CurrentRequestFinsDevId);
                            if (dev_value != null) {
                                jsonReturn.put("code", FinsStatus.SUCCESS);
                                jsonReturn.put("msg", "通风控制PLC数据获取成功");
                                deviceInfo.put(json.getString("registerAddress") + json.getString("bits"), dev_value);
                            } else {
                                jsonReturn.put("code", FinsStatus.NO_RETURN_DATA);
                                jsonReturn.put("msg", "通风控制PLC数据未获取成功");
                                deviceInfo.put(json.getString("registerAddress") + json.getString("bits"), "NoData");
                            }
                        }
                        // 将数据传到了网页
                        jsonReturn.put("deviceInfo", deviceInfo);
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                        return;
                    }
                    // 写操作
                    else if (json.get("type").equals("write")) {
                        finsMessage = FinsMessageUtils.createWriteMessage(json.getInt("memoryArea"), json.getInt("registerAddress"),
                            json.getInt("bits"), json.getInt("value"), serverpath);
                        // 二次判断，看fins数据是否生成
                        if (finsMessage != null) {
                            // 把fins消息发送给plc
                            if (channelFuture != null && channelFuture.isSuccess()) {
                                // 将finse数据发给plc
                                channelFuture.channel().writeAndFlush(finsMessage.toString()).sync();
                                // 生成发送给网页的数据
                                Map<String, String> deviceInfo = new HashMap<String, String>();
                                deviceInfo.put("memoryArea", json.containsKey("memoryArea") ? json.getString("memoryArea") : null);
                                deviceInfo.put("registerAddress", json.containsKey("registerAddress") ? json.getString("registerAddress") : null);
                                deviceInfo.put("bits", json.containsKey("bits") ? json.getString("bits") : null);
                                deviceInfo.put("length", json.containsKey("length") ? json.getString("length") : null);
                                deviceInfo.put("value", json.containsKey("value") ? json.getString("value") : null);
                                jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                                jsonReturn.put("tunnelId", json.containsKey("tunnelId") ? json.getString("tunnelId") : null);
                                jsonReturn.put("moduleId", json.containsKey("moduleId") ? json.getString("moduleId") : null);
                                jsonReturn.put("code", FinsStatus.SEND_SUCCESS);
                                jsonReturn.put("msg", "通风控制PLC设备设置成功");
                                jsonReturn.put("deviceInfo", deviceInfo);
                                // 将操作成功的数据上发给网页端
                                ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                            }
                        }
                    }
                    // 指令错误
                    else {
                        jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                        jsonReturn.put("code", FinsStatus.COMMAND_ERROR);
                        jsonReturn.put("msg", "操作指令错误");
                        // 发送操作指令的信息给网页
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                        log.info("操作指令错误");
                    }
                    return;
                }
                // 视觉诱导模块
                if(json.get("moduleId").equals(ModuleIdList.VISUAL_INDUCTION)){
                    // 创建发送给plc的fins消息
                    FinsMessage finsMessage = null;
                    // 筛选出服务列表
                    List<ServerEqFormal> visualinductionserverList = serverService.selectServerformalByInfo(json.getInt("tunnelId"), json.getInt("moduleId"),
                        json.containsKey("server_name_En")?json.getString("server_name_En"):null);
//                    List<ServerEq> visualinductionserverList = serverService.selectServerByTunnelId(json.getLong("tunnelId"), json.getLong("moduleId"));
                    Map<String, ChannelFuture> connectMap = NettyStarter.getConnectMap(); // 通过netty获取所有连接状态
                    // 对服务列表进行筛选，只保留处于连接的设备
                    for(int i = 0; i < visualinductionserverList.size(); i++) {
                        if(!connectMap.containsKey(visualinductionserverList.get(i).getHost() + ":" +visualinductionserverList.get(i).getPort())){
                            visualinductionserverList.remove(i);
                            i--;
                        }
                    }
                    // 判断服务数量是否正常，唯一才是正常的
                    if(visualinductionserverList.size()!=1){
                        Map<String,String> deviceInfo = new HashMap<String,String>();
                        deviceInfo.put("memoryArea", json.containsKey("memoryArea") ? json.getString("memoryArea") : null);
                        deviceInfo.put("registerAddress", json.containsKey("registerAddress") ? json.getString("registerAddress") : null);
                        deviceInfo.put("bits", json.containsKey("bits") ? json.getString("bits") : null);
                        deviceInfo.put("length", json.containsKey("length") ? json.getString("length") : null);
                        jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                        jsonReturn.put("tunnelId", json.containsKey("tunnelId") ? json.getString("tunnelId") : null);
                        jsonReturn.put("moduleId", json.containsKey("moduleId") ? json.getString("moduleId") : null);
                        if(visualinductionserverList.size()==0){
                            jsonReturn.put("code", FinsStatus.NO_DEVICE);
                            jsonReturn.put("msg", "无视觉诱导PLC设备连接");
                            jsonReturn.put("deviceInfo", deviceInfo);
                        }
                        if(visualinductionserverList.size()>1){
                            jsonReturn.put("code", FinsStatus.DEVICE_OVERQUANTUTY);
                            jsonReturn.put("msg", "视觉诱导PLC设备不唯一");
                            jsonReturn.put("deviceInfo", deviceInfo);
                        }
                        // 将报警信息发送给前端
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                        return;
                    }
                    // 获取完整地址
                    String serverpath = visualinductionserverList.get(0).getHost()+":"+visualinductionserverList.get(0).getPort();
//                    String serverpath = "127.0.0.1:8099";
                    String dev_value = "0";
                    // 获取连接
                    ChannelFuture channelFuture = connectMap.get(serverpath);
                    // 读操作
                    if(json.get("type").equals("query")){
                        jsonReturn.clear();
                        jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                        jsonReturn.put("tunnelId", json.containsKey("tunnelId") ? json.getString("tunnelId") : null);
                        jsonReturn.put("moduleId", json.containsKey("moduleId") ? json.getString("moduleId") : null);
                        Map<String,String> deviceInfo = new HashMap<String,String>();
                        // 多设备状态查询,复用memoryArea查询是否为设备查询
                        if(json.getInt("memoryArea")==9999){
                            List<ServerPointFormal> visualInductionPointList=new ArrayList<>();
                            if(currentactivemodule.equals(ActiveModule.VISUAL_INDUCTION_24)){
                                visualInductionPointList= serverPointService.getserverpoint(3);
                            }
                            else if(currentactivemodule.equals(ActiveModule.VISUAL_INDUCTION_25)){
                                visualInductionPointList= serverPointService.getserverpoint(4);
                            }
                            if(visualInductionPointList.size()>0){
                                for(ServerPointFormal serverPointFormal:visualInductionPointList){
                                    int tunnelId = serverPointFormal.getTunnel_id();
                                    int moduleId = serverPointFormal.getModule_id();
                                    int memoryArea = serverPointFormal.getMemory_area();
                                    int registerAddress = (int) serverPointFormal.getRegister_address();
                                    int length = serverPointFormal.getLength();
                                    int bits = serverPointFormal.getBits();
                                    dev_value = redisCache.getCacheObject("fins_plc/"+tunnelId+"/"+moduleId+"/"+memoryArea+"/"+registerAddress+"/"+length+"/"+bits);
                                    // 复用registerAddress信息存数据
                                    if(dev_value!=null){
                                        jsonReturn.put("code", FinsStatus.SUCCESS);
                                        jsonReturn.put("msg", "视觉诱导PLC数据获取成功");
                                        deviceInfo.put(String.valueOf(registerAddress), dev_value);
                                    }
                                    else {
                                        jsonReturn.put("code", FinsStatus.NO_RETURN_DATA);
                                        jsonReturn.put("msg", "视觉诱导PLC数据未成功");
                                        deviceInfo.put(String.valueOf(registerAddress), "NoData");
                                    }
                                }
                            }
                        }
                        // 单查询
                        else {
                            String CurrentRequestFinsDevId = "fins_plc/"+ json.getString("tunnelId")+"/"+
                                json.getString("moduleId")+"/"+
                                json.getString("memoryArea")+"/"+
                                json.getString("registerAddress")+"/"+
                                json.getString("length")+"/"+
                                json.getString("bits");
                            dev_value = redisCache.getCacheObject(CurrentRequestFinsDevId);
                            if(dev_value!=null){
                                jsonReturn.put("code", FinsStatus.SUCCESS);
                                jsonReturn.put("msg", "视觉诱导PLC数据获取成功");
                                deviceInfo.put(json.getString("registerAddress"), dev_value);
                            }
                            else {
                                jsonReturn.put("code", FinsStatus.NO_RETURN_DATA);
                                jsonReturn.put("msg", "视觉诱导PLC数据未成功");
                                deviceInfo.put(json.getString("registerAddress"), "NoData");
                            }
                        }
                        // 将数据传到了网页
                        jsonReturn.put("deviceInfo", deviceInfo);
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                    }
                    // 写操作
                    else if(json.get("type").equals("write")){
                        finsMessage = FinsMessageUtils.createWriteMessage(json.getInt("memoryArea"), json.getInt("registerAddress"),
                            json.getInt("bits"), json.getInt("value"), serverpath);

                        String finsMessageStr = finsMessage.toString();
                        String valueStr = String.format("%x", json.getInt("value"));
                        // 补全位数，必要的
                        if(valueStr.length()<=1){
                            valueStr = "0"+valueStr;
                        }
                        String finsMessageStrAmend = finsMessageStr.substring(0,finsMessageStr.length()-2) + valueStr;
//                        System.out.println(finsMessageStrAmend);
                        // 二次判断，看fins数据是否生成
                        if (finsMessage != null){
                            // 把fins消息发送给plc
                            if (channelFuture != null && channelFuture.isSuccess()) {
                                // 将finse数据发给plc
                                channelFuture.channel().writeAndFlush(finsMessageStrAmend).sync();
                                // 生成发送给网页的数据
                                Map<String,String> deviceInfo = new HashMap<String,String>();
                                deviceInfo.put("memoryArea", json.containsKey("memoryArea") ? json.getString("memoryArea") : null);
                                deviceInfo.put("registerAddress", json.containsKey("registerAddress") ? json.getString("registerAddress") : null);
                                deviceInfo.put("bits", json.containsKey("bits") ? json.getString("bits") : null);
                                deviceInfo.put("length", json.containsKey("length") ? json.getString("length") : null);
                                deviceInfo.put("value", json.containsKey("value") ? json.getString("value") : null);
                                jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                                jsonReturn.put("tunnelId", json.containsKey("tunnelId") ? json.getString("tunnelId") : null);
                                jsonReturn.put("moduleId", json.containsKey("moduleId") ? json.getString("moduleId") : null);
                                jsonReturn.put("code", FinsStatus.SEND_SUCCESS);
                                jsonReturn.put("msg", "视觉诱导PLC设备设置成功");
                                jsonReturn.put("deviceInfo", deviceInfo);
                                // 将操作成功的数据上发给网页端
                                ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                            }
                        }
                    }
                    // 指令错误
                    else {
                        jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                        jsonReturn.put("code", FinsStatus.COMMAND_ERROR);
                        jsonReturn.put("msg", "操作指令错误");
                        // 发送操作指令的信息给网页
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                        log.info("操作指令错误");
                    }
                    return;
                }
                // 隧道消防模块,发过来的数据，tunnelId一定要设为0，在数据库中，消防模块的id为0
                if(json.get("moduleId").equals(ModuleIdList.INTELLIGENT_FIRE_BOX)){

                    // 筛选出服务列表
                    List<ServerEqFormal> fireboxserverList = serverService.selectServerformalByInfo(json.getInt("tunnelId"), json.getInt("moduleId"),
                        json.containsKey("servernameEn")?json.getString("servernameEn"):null);
                    Map<String, ChannelFuture> connectMap = NettyStarter.getConnectMap(); // 通过netty获取所有连接状态
                    // 对服务列表进行筛选，只保留处于连接的服务
                    for(int i = 0; i < fireboxserverList.size(); i++) {
                        if(!connectMap.containsKey(fireboxserverList.get(i).getHost() + ":" +fireboxserverList.get(i).getPort())){
                            fireboxserverList.remove(i);
                            i--;
                        }
                    }
                    // 如果服务列表为0，则说明没有连接，发送连接失败信息，然后直接返回
                    if(fireboxserverList.size()!=1){
                        Map<String,String> deviceInfo = new HashMap<String,String>();
                        jsonReturn.put("tunnelId", json.containsKey("tunnelId") ? json.getString("tunnelId") : null);
                        jsonReturn.put("moduleId", json.containsKey("moduleId") ? json.getString("moduleId") : null);
                        jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                        if(fireboxserverList.size()==0){
                            jsonReturn.put("code", FinsStatus.NO_DEVICE);
                            jsonReturn.put("msg", "无智能消防箱设备连接");
                            jsonReturn.put("deviceInfo", deviceInfo);
                        }
                        if(fireboxserverList.size()>1){
                            jsonReturn.put("code", FinsStatus.DEVICE_OVERQUANTUTY);
                            jsonReturn.put("msg", "智能消防箱设备不唯一");
                            jsonReturn.put("deviceInfo", deviceInfo);
                        }
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                        return;
                    }
                    // 下面代表服务正常
                    // 获取完整地址
                    String fireboxserverpath = fireboxserverList.get(0).getHost()+":"+fireboxserverList.get(0).getPort();
                    // *********判断是否为查询状态的指令，消防箱只能查询,复用registerAddress和length查询数据
                    if (json.getString("type").equals(ReturnType.QUERY.getCode())){
                        String fire_box_data_key = "fire_box/"+json.getLong("memoryArea")+"/"+json.getLong("registerAddress");
                        String fire_box_data = redisCache.getCacheObject(fire_box_data_key);
                        Map<String,String> deviceInfo = new HashMap<String,String>();
                        jsonReturn.put("tunnelId", json.containsKey("tunnelId") ? json.getString("tunnelId") : null);
                        jsonReturn.put("moduleId", json.containsKey("moduleId") ? json.getString("moduleId") : null);
                        // 无数据就返回了
                        if(fire_box_data==null){
                            jsonReturn.put("code", FinsStatus.NO_RETURN_DATA);
                            jsonReturn.put("msg", "获取fire_box数据失败");
                            jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                            jsonReturn.put("servernameEn", json.containsKey("servernameEn") ? json.getString("servernameEn") : 0);
                            jsonReturn.put("deviceInfo", deviceInfo);
                            ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                            return;
                        }
                        // 将消防箱数据转换成json
                        deviceInfo = DataUtils.fireboxdataprocess(fire_box_data);

                        jsonReturn.put("code", FinsStatus.SUCCESS);
                        jsonReturn.put("msg", "获取fire_box数据成功");
                        jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                        jsonReturn.put("servernameEn", json.containsKey("servernameEn") ? json.getString("servernameEn") : 0);
                        jsonReturn.put("deviceInfo", deviceInfo);
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                    }
                    return;
                }
                // 二次事故管控模块（plc-fins设备）
                else if(json.get("moduleId").equals(ModuleIdList.SECONDARY_ACCIDENT)){
                    // 创建发送给plc的fins消息
                    FinsMessage finsMessage = null;
                    // 统计连接PLC服务状态
                    // 先根据隧道id、以及模块id获取plc列表，以便筛选出本模块对应的设备
                    List<ServerEqFormal> secondaryaccidentserverList = serverService.selectServerformalByInfo(json.getInt("tunnelId"), json.getInt("moduleId"),
                        json.containsKey("servernameEn")?json.getString("servernameEn"):null);
//                    List<ServerEq> serverList = serverService.selectServerByTunnelId(json.getLong("tunnelId"), json.getLong("moduleId"));
                    Map<String, ChannelFuture> connectMap = NettyStarter.getConnectMap(); // 通过netty获取所有连接状态
                    // 对服务列表进行筛选，只保留处于连接的服务，
                    for(int i = 0; i < secondaryaccidentserverList.size(); i++) {
                        if(!connectMap.containsKey(secondaryaccidentserverList.get(i).getHost() + ":" +secondaryaccidentserverList.get(i).getPort())){
                            secondaryaccidentserverList.remove(i);
                            i--;
                        }
                    }
                    // 如果服务列表为0，则说明没有连接，发送连接失败信息，然后直接返回
                    if(secondaryaccidentserverList.size()!=1){
                        Map<String,String> deviceInfo = new HashMap<String,String>();
                        deviceInfo.put("memoryArea", json.containsKey("memoryArea") ? json.getString("memoryArea") : null);
                        deviceInfo.put("registerAddress", json.containsKey("registerAddress") ? json.getString("registerAddress") : null);
                        deviceInfo.put("bits", json.containsKey("bits") ? json.getString("bits") : null);
                        deviceInfo.put("length", json.containsKey("length") ? json.getString("length") : null);
                        jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                        if(secondaryaccidentserverList.size()==0){
                            jsonReturn.put("code", FinsStatus.NO_DEVICE);
                            jsonReturn.put("msg", "无二次事故管控PLC设备连接");
                            jsonReturn.put("tunnelId", json.containsKey("tunnelId") ? json.getString("tunnelId") : null);
                            jsonReturn.put("moduleId", json.containsKey("moduleId") ? json.getString("moduleId") : null);
                            jsonReturn.put("deviceInfo", deviceInfo);
                        }
                        if(secondaryaccidentserverList.size()>1){
                            jsonReturn.put("code", FinsStatus.DEVICE_OVERQUANTUTY);
                            jsonReturn.put("msg", "二次事故管控PLC设备不唯一");
                            jsonReturn.put("tunnelId", json.containsKey("tunnelId") ? json.getString("tunnelId") : null);
                            jsonReturn.put("moduleId", json.containsKey("moduleId") ? json.getString("moduleId") : null);
                            jsonReturn.put("deviceInfo", deviceInfo);
                        }
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                        return;
                    }
                    // 如果服务的数量正常，连接正常
                    // 完整plc服务设备的地址
                    String serverpath = secondaryaccidentserverList.get(0).getHost()+":"+secondaryaccidentserverList.get(0).getPort();
                    String dev_value = "0";
                    // *********判断是否为查询状态的指令
                    if (json.getString("type").equals(ReturnType.QUERY.getCode())) {
                        jsonReturn.clear();
                        jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                        jsonReturn.put("tunnelId", json.containsKey("tunnelId") ? json.getString("tunnelId") : null);
                        jsonReturn.put("moduleId", json.containsKey("moduleId") ? json.getString("moduleId") : null);
                        Map<String,String> deviceInfo = new HashMap<String,String>();
                        // 多设备状态查询,复用memoryArea查询是否为设备查询
                        if(json.getInt("memoryArea")==9999){
                            List<ServerPointFormal> secondryControlPointList=new ArrayList<>();
                            if(currentactivemodule.equals(ActiveModule.SECONDARY_ACCIDENT_24)){
                                secondryControlPointList= serverPointService.getserverpoint(1);
                            }
                            else if(currentactivemodule.equals(ActiveModule.SECONDARY_ACCIDENT_25)){
                                secondryControlPointList= serverPointService.getserverpoint(2);
                            }
                            if(secondryControlPointList.size()>0){
                                for(ServerPointFormal serverPointFormal:secondryControlPointList){
                                    int tunnelId = serverPointFormal.getTunnel_id();
                                    int moduleId = serverPointFormal.getModule_id();
                                    int memoryArea = serverPointFormal.getMemory_area();
                                    int registerAddress = (int) serverPointFormal.getRegister_address();
                                    int length = serverPointFormal.getLength();
                                    int bits = serverPointFormal.getBits();
                                    dev_value = redisCache.getCacheObject("fins_plc/"+tunnelId+"/"+moduleId+"/"+memoryArea+"/"+registerAddress+"/"+length+"/"+bits);
                                    // 复用registerAddress信息存数据
                                    if(dev_value!=null){
                                        jsonReturn.put("code", FinsStatus.SUCCESS);
                                        jsonReturn.put("msg", "二次事故PLC数据获取成功");
                                        deviceInfo.put(String.valueOf(registerAddress), dev_value);
                                    }
                                    else {
                                        jsonReturn.put("code", FinsStatus.NO_RETURN_DATA);
                                        jsonReturn.put("msg", "二次事故PLC数据未成功");
                                        deviceInfo.put(String.valueOf(registerAddress), "NoData");
                                    }
                                }
                            }
                        }
                        // 单设备查询
                        else {
                            String CurrentRequestFinsDevId = "fins_plc/"+ json.getString("tunnelId")+"/"+
                                json.getString("moduleId")+"/"+
                                json.getString("memoryArea")+"/"+
                                json.getString("registerAddress")+"/"+
                                json.getString("length")+"/"+
                                json.getString("bits");
                            dev_value = redisCache.getCacheObject(CurrentRequestFinsDevId);
                            if(dev_value!=null){
                                jsonReturn.put("code", FinsStatus.SUCCESS);
                                jsonReturn.put("msg", "二次事故PLC数据获取成功");
                                deviceInfo.put(json.getString("registerAddress"), dev_value);
                            }
                            else {
                                jsonReturn.put("code", FinsStatus.NO_RETURN_DATA);
                                jsonReturn.put("msg", "二次事故PLC数据未成功");
                                deviceInfo.put(json.getString("registerAddress"), "NoData");
                            }
                        }
                        // 将数据传到了网页
                        jsonReturn.put("deviceInfo", deviceInfo);
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                        return;
                    }
                    // ***********判断是否为写设备指令
                    else if (json.getString("type").equals(ReturnType.WRITE.getCode())) {
                        dev_value = json.getString("value");
                        // 点位数据直接从前端取
                        finsMessage = FinsMessageUtils.createWriteMessage(json.getInt("memoryArea"), json.getInt("registerAddress"),
                                                                          json.getInt("bits"), json.getInt("value"), serverpath);
                    }
                    // 指令错误
                    else {
                        jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                        jsonReturn.put("code", FinsStatus.COMMAND_ERROR);
                        jsonReturn.put("msg", "操作指令错误");
                        // 发送操作指令的信息给网页
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                        log.info("操作指令错误");
                        return;
                    }
                    // 二次判断，看fins数据是否生成
                    if (finsMessage != null) {
                        RLock redissonLock = redisson.getLock(lockKey);
                        // 锁  缓存redis
                        redissonLock.lock(3, TimeUnit.SECONDS);
                        log.info(DateUtils.dateTimeNow());
                        ChannelFuture channelFuture = connectMap.get(serverpath);
                        // 创建上传的数据
                        Map<String,String> deviceInfo = new HashMap<String,String>();
                        deviceInfo.put("memoryArea", json.containsKey("memoryArea") ? json.getString("memoryArea") : null);
                        deviceInfo.put("registerAddress", json.containsKey("registerAddress") ? json.getString("registerAddress") : null);
                        deviceInfo.put("bits", json.containsKey("bits") ? json.getString("bits") : null);
                        deviceInfo.put("length", json.containsKey("length") ? json.getString("length") : null);
                        deviceInfo.put("value", dev_value);

                        jsonReturn.put("operateType", json.containsKey("type") ? json.getString("type") : 0);
                        jsonReturn.put("tunnelId", json.containsKey("tunnelId") ? json.getString("tunnelId") : null);
                        jsonReturn.put("moduleId", json.containsKey("moduleId") ? json.getString("moduleId") : null);
                        jsonReturn.put("code", FinsStatus.SEND_SUCCESS);
                        jsonReturn.put("msg", "PLC指令下发成功");
                        jsonReturn.put("deviceInfo", deviceInfo);
                        // 把fins消息发送给plc
                        if (channelFuture != null && channelFuture.isSuccess()) {
                            // 将finse数据发给plc
                            channelFuture.channel().writeAndFlush(finsMessage.toString()).sync();
                            // 将操作成功的数据上发给网页端
                            ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonReturn.toString()));
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            jsonReturn.clear();
            jsonReturn.put("code", FinsStatus.OPERATION_EXECPTION);
            jsonReturn.put("msg", "操作异常");
            jsonReturn.put("operateType", json.containsKey("operateType") ? json.getLong("operateType") : null);
            jsonReturn.put("tunnelId", json.containsKey("tunnelId") ? json.getLong("tunnelId") : null);
            jsonReturn.put("moduleId", json.containsKey("moduleId") ? json.getLong("moduleId") : null);
            ctx.channel().writeAndFlush(new TextWebSocketFrame(json.toString()));
            MyChannelHandlerPool.tcpChannelGroup.writeAndFlush(Unpooled.wrappedBuffer(JSON.stringify(json).getBytes(CharsetUtil.UTF_8)));
        } finally {
            ReferenceCountUtil.release(msg);
        }

    }
}
